<template>
  <view v-show="pageLoaded">
    <view class="cart-box">
      <view class="shop-list" v-for="store in list" :key="store.storeId">
        <view class="shop-info-box">
          <view class="shop-info" @click="toPage(`/page_mall/shop/shop?id=${store.storeId}`)">
            <view
              class="radio"
              :class="{ checked: store.isAllActive }"
              @click="select('store', {}, !store.isAllActive, store)"
            ></view>
            <view class="shop-image-box">
              <image
                class="shop-image"
                :src="`${img_baseUrl}/statics/std/static/new/shop_green.png`"
              />
            </view>
            <view class="shop-title">{{ store.storeName }}</view>
          </view>
        </view>
        <view class="product-list">
          <view class="item" v-for="goods in store.goods" :key="goods.id">
            <view
              class="radio"
              :class="{checked: goods.isActive, disable: goods.goodsStatus === '0'}"
              @click="select('goods', goods, !goods.isActive, store)"
            ></view>
            <view class="product-img-box">
              <image class="product-img" :src="img_baseUrl + goods.imgAbbrev" />
            </view>
            <view class="product-right">
              <view class="product-title" @click="toPage(`/page_mall/detail/detail?id=${goods.goodsId}`)">{{ goods.name }}</view>
              <view class="product-type" v-if="goods.goodsSpec">
                {{ goods.goodsSpec }}
              </view>
              <view class="price-num-box">
                <view class="price">¥{{ goods.toShowPrice }}</view>
                <number-box
                  v-if="goods.goodsStatus == '1'"
                  :min="0"
                  :value="goods.goodsNum"
                  @input="
                    (num) => {
                      changeNum(goods, num);
                    }
                  "
                />
                <view class="product-expire" v-else>
                  <text>已过期</text>
                  <text style="color: #EA3D3D;margin-left: 12rpx;" @click="changeNum(goods, 0)">删除商品</text>
                </view>
              </view>
            </view>
          </view>
        </view>
      </view>
      <view class="noData" v-if="list.length === 0">
        <image :src="`${img_baseUrl}/statics/std/static/noData.png`" />
        <text>购物车是空的，快去买点什么吧</text>
      </view>
    </view>
    <view class="btn-box">
      <view
        class="btn-operate-box"
        @click="select('all', {}, !isAllGoodsActive, {})"
      >
        <view class="radio" :class="{ checked: isAllGoodsActive }"></view>
        <view class="btn-operate-text">全选</view>
      </view>
      <view class="count-price-box">
        <view class="count-label">已选{{ goodsCountNum }}件</view>
        <view>
          <text>总计</text>
          <text class="count-value">¥{{ goodsCountPrice }}</text>
        </view>
      </view>
      <view class="go-pay" @click="toPay">结算</view>
    </view>
  </view>
</template>

<script>
import { Decimal } from "decimal.js";
import requestPost, { requestDelete, requestGet } from "../../utils/request";
import numberBox from "../../components/number-box.vue";

const img_api = process.env.VUE_APP_BASEURL_IMG_API;

export default {
  components: {
    numberBox,
  },
  data() {
    return {
      pageLoaded: false,
      loading: 2, // 0:不再加载; 1:加载中; 2:加载完成;
      img_baseUrl: img_api,
      pageNum: 1,
      pageSize: 100,
      sourceList: [],
      list: [],
      isAllGoodsActive: false,
      timerChangeNum: 0,
    };
  },
  computed: {
    isActiveList() {
      return this.list.map((store) => {
        return store.goods.every((goods) => {
          return goods.isActive;
        });
      });
    },
    goodsCountNum() {
      return this.list.reduce((acc, store) => {
        return (
          acc +
          store.goods.filter((goods) => {
            return goods.isActive;
          }).length
        );
      }, 0);
    },
    goodsCountPrice() {
      return this.list
        .reduce((acc, store) => {
          return store.goods.reduce((_acc, goods) => {
            return goods.isActive
              ? new Decimal(_acc)
                  .add(
                    new Decimal(goods.price).mul(new Decimal(goods.goodsNum))
                  )
                  .toNumber()
              : _acc;
          }, acc);
        }, 0)
        .toFixed(2);
    },
  },
  watch: {
    isActiveList() {
      // 更新店铺选项控件
      for (const activeListKey in this.isActiveList) {
        this.list[activeListKey].isAllActive = this.isActiveList[activeListKey];
      }
      // 更新全局选项控件
      this.isAllGoodsActive = this.isActiveList.every((active) => {
        return active;
      });
    },
  },
  onShow() {
    this.pageNum = 1;
    this.list = [];
    this.loadList().then(() => {
      this.pageLoaded = true;
    });
  },
  onReachBottom() {
    this.loadNextPage();
  },
  methods: {
    toPage(url, params = {}) {
      let paramsString = "";
      for (const paramsKey in params) {
        if (!paramsString) {
          paramsString += "?";
        } else {
          paramsString += "&";
        }
        paramsString += `${paramsKey}=${params[paramsKey]}`;
      }
      uni.navigateTo({
        url: `${url}${paramsString}`,
      });
    },
    select(type, goods, active, store) {
      if (type === "all") {
        for (const store of this.list) {
          for (const _goods of store.goods.filter(i => i.goodsStatus == '1')) {
            this.$set(_goods, 'isActive', active)
          }
        }
      }
      if (type === "store") {
        for (const _goods of store.goods.filter(i => i.goodsStatus == '1')) {
          this.$set(_goods, 'isActive', active)
        }
      }
      if (type === "goods") {
        if(goods.goodsStatus == '1') this.$set(goods, 'isActive', active);
      }
    },
    changeNum(goods, num) {
      if (num === 0) {
        let globalIndex = -1;
        this.list.forEach((store, index) => {
          let _index = store.goods.findIndex((_goods) => {
            return _goods.id === goods.id;
          });
          if (_index !== -1) {
            store.goods.splice(_index, 1);
          }
          if (store.goods.length === 0) {
            globalIndex = index;
          }
        });
        if (globalIndex !== -1) {
          this.list.splice(globalIndex, 1);
        }
      }else{
        this.list.forEach((store, index) => {
          let _index = store.goods.findIndex((_goods) => {
            return _goods.id === goods.id;
          });
          if (_index !== -1) {
            this.$set(store.goods[_index], 'goodsNum', num)
          }
          
        });
      }
      clearTimeout(this.timerChangeNum);
      this.timerChangeNum = setTimeout(() => {
        if (num !== 0) {
          // 编辑购物车商品数量
          requestPost(
            "/shop/mobile/cart",
            {
              id: goods.id,
              goodsNum: num,
            },
            "",
            "PUT"
          );
        } else {
          // 删除购物车商品
          requestDelete(`/shop/mobile/cart/${goods.id}`);
        }
      }, 500);
    },
    toPay() {
      if (this.goodsCountNum === 0) return;
      let selectGoods = [],
        countSelectStore = new Set();
      for (const store of this.list) {
        for (const _goods of store.goods) {
          if (_goods.isActive) {
            selectGoods.push(_goods);
            countSelectStore.add(store.storeId);
          }
        }
      }
      if (countSelectStore.size > 1) {
        uni.showToast({
          title: "抱歉，无法同时结算多个商店商品。",
          icon: "none",
        });
        return;
      }
      this.$store.commit(
        "setSettlementGoods",
        selectGoods.map((goods) => {
          return {
            id: goods.id, // 购物车id
            storeId: goods.storeId, // 店铺id
            storeName: goods.storeName, // 店铺名称
            goodsId: goods.goodsId, // 商品id
            goodsNum: goods.goodsNum, // 商品数量
            goodsSpec: goods.goodsSpec, // 规格
            name: goods.name, // 商品名称
            imgAbbrev: goods.imgAbbrev, // 商品缩略图
            price: goods.price, // 商品价格
            ...(goods.skuId ? { skuId: goods.skuId } : {}),
          };
        })
      );
      console.log(this.$store.state.settlementGoods);
      this.toPage("/page_mall/settle/index");
    },
    formatData(list, newList) {
      const grouped = newList.reduce((acc, item) => {
        if (!acc[item.storeId]) {
          acc[item.storeId] = {
            storeId: item.storeId,
            storeName: item.storeName,
            isAllActive: false,
            goods: [],
          };
        }
        acc[item.storeId].goods.push({
          ...item,
          toShowPrice: item.price?.toFixed(2),
          isActive: acc[item.storeId].isAllActive,
        });
        return acc;
      }, list);
      return Object.values(grouped);
    },
    loadNextPage() {
      if (this.loading === 0 || this.loading === 1) return;
      this.pageNum++;
      this.loadList();
    },
    loadList() {
      if (this.loading === 1) {
        return Promise.reject({
          msg: "loading...",
        });
      }
      this.loading = 1;
      return requestGet("/shop/mobile/cart/list", {
        pageNum: this.pageNum,
        pageSize: this.pageSize,
      }).then(({ code, rows: lists, total }) => {
        if (code !== 200) {
          lists = [];
          total = 0;
        }
        if (this.pageNum === 1) {
          this.sourceList = [].concat(lists);
          this.list = this.formatData([], lists);
        } else {
          this.sourceList = this.sourceList.concat(lists);
          this.list = this.formatData(this.list, lists);
        }
        if (lists.length < this.pageSize || total === this.sourceList.length) {
          this.loading = 0;
        } else {
          this.loading = 2;
        }
      });
    },
  },
};
</script>

<style lang="scss">
page {
  background: #f7f9fa;
}

.radio {
  flex: none;
  width: 40rpx;
  height: 40rpx;
  background: #ffffff;
  border: 4rpx solid #b7c1ca;
  border-radius: 50%;
  margin-right: 24rpx;
  box-sizing: border-box;

  &.disabled {
    background: #eceff1;
    border: 4rpx solid #b7c1ca;
  }

  &.checked {
    background: url("../../static/new/radio-checked.png")
      no-repeat;
    border: none;
    background-size: 100% 100%;
  }
  &.disable{
    background: #ECEFF1 !important;
  }
}

.cart-box {
  padding: 24rpx 32rpx calc(124rpx + env(safe-area-inset-bottom));
  background: #f7f9fa;

  .shop-list {
    background: #ffffff;
    border-radius: 24rpx;
  }

  .shop-info-box {
    padding-top: 24rpx;
    padding-left: 16rpx;
  }

  .shop-info {
    padding: 4rpx 0;
    display: flex;
    align-items: center;

    .shop-image-box {
      width: 40rpx;
      height: 40rpx;
      margin-right: 16rpx;

      .shop-image {
        display: block;
        width: 100%;
        height: 100%;
      }
    }

    .shop-title {
      font-size: 28rpx;
      font-weight: 400;
      color: #777f8f;
      line-height: 40rpx;
    }
  }

  .product-list {
    padding: 0rpx 24rpx 24rpx 16rpx;
    margin-bottom: 24rpx;

    .item {
      display: flex;
      align-items: center;
      padding-top: 48rpx;
    }

    .product-img-box {
      flex: none;
      width: 160rpx;
      height: 160rpx;
      margin-right: 24rpx;

      .product-img {
        display: block;
        width: 100%;
        height: 100%;
        border-radius: 16rpx;
      }
    }

    .product-right {
      flex: auto;
      height: 160rpx;
      display: flex;
      flex-flow: column nowrap;
    }

    .product-title {
      font-size: 32rpx;
      font-weight: 400;
      color: rgba(0, 0, 0, 0.8);
      line-height: 44rpx;
    }

    .product-type {
      display: inline-block;
      background: #f7f9fa;
      padding: 4rpx 8rpx;
      border-radius: 8rpx;
      font-size: 24rpx;
      font-weight: 400;
      color: #5f6f86;
      line-height: 32rpx;
      margin-top: 16rpx;
      align-self: flex-start;
    }

    .price-num-box {
      height: 48rpx;
      margin-top: auto;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .price {
      font-size: 32rpx;
      font-weight: 700;
      color: #ff7614;
      line-height: 34rpx;
      padding-top: 6rpx;
    }

    .product-expire {
      font-size: 24rpx;
      font-weight: 400;
      color: rgba(0, 0, 0, 0.3);
      line-height: 34rpx;
    }
  }
}

.noData {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 500rpx;

  image {
    height: 240rpx;
    width: 240rpx;
    flex: 0 0 auto;
  }

  text {
    font-size: 24rpx;
    font-weight: 400;
    color: rgba(0, 0, 0, 0.3);
    line-height: 34rpx;
  }
}

.btn-box {
  display: flex;
  align-items: center;
  position: fixed;
  bottom: 0;
  width: 100%;
  height: 124rpx;
  background: #ffffff;
  border-radius: 0rpx 0rpx 0rpx 0rpx;
  border: 2rpx solid rgba(0, 0, 0, 0.1);
  padding-bottom: env(safe-area-inset-bottom);

  .btn-operate-box {
    margin-left: 48rpx;
    display: flex;
    align-items: center;

    .btn-operate-text {
      font-size: 24rpx;
      font-weight: 400;
      color: rgba(0, 0, 0, 0.5);
      line-height: 34rpx;
    }
  }

  .count-price-box {
    margin-left: auto;
    font-size: 24rpx;
    font-weight: 400;
    color: rgba(0, 0, 0, 0.7);
    line-height: 34rpx;
    display: flex;
    flex-flow: column nowrap;
    align-items: flex-end;

    .count-label {
      color: rgba(0, 0, 0, 0.5);
      margin-bottom: 10rpx;
    }
  }

  .count-value {
    font-size: 36rpx;
    font-weight: 700;
    color: #ff7614;
    line-height: 44rpx;
    margin-left: 16rpx;
  }

  .go-pay {
    width: 240rpx;
    height: 88rpx;
    margin-left: 28rpx;
    margin-right: 32rpx;
    background: #3FAA73;
    border-radius: 44rpx 44rpx 44rpx 44rpx;
    font-size: 32rpx;
    font-weight: 500;
    color: #ffffff;
    line-height: 88rpx;
    text-align: center;
  }
}
</style>
